﻿// Decompiled with JetBrains decompiler
// Type: DnProcessSimulateCommands.AutomaticInterferenceVolumeCreation.CApAIVCInterferenceVolumesCreator
// Assembly: DnProcessSimulateCommands, Version=2402.0.0.890, Culture=neutral, PublicKeyToken=null
// MVID: A885D881-AEDF-447E-852A-6F13102E089C
// Assembly location: C:\Program Files\Tecnomatix_2402\eMPower\DotNetCommands\DnProcessSimulateCommands.dll

using DnProcessSimulateCommands.InterferenceVolume;
using EngineeringInternalExtension;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using Tecnomatix.Engineering;


namespace DnProcessSimulateCommands.AutomaticInterferenceVolumeCreation;

internal class CApAIVCInterferenceVolumesCreator
{
  private CApIVInterferenceVolumeCreator m_ivCreator;
  private CApAIVCInterferenceVolumeDataProvider m_ivData;
  private TxInterferenceVolume_MayProceedCalculation m_mayProceedCallback;
  private CApAIVCLogMessageEventHandler m_logMessage;
  private bool m_shouldStop;
  private TxObjectList m_sweptVolumes;
  private TxObjectList m_interferenceVolumes;
  private TxObjectList m_redundantSVs;
  private List<KeyValuePair<TxSweptVolume, TxSweptVolume>> m_collidedSVs;
  private TxObjectList m_volumesToClear;
  private TxSweptVolume m_currentVolumeToClear;
  private TxCollisionQueryParams m_queryParams;
  private TxCollisionPair m_collisionPair;
  private TxObjectList m_activePairs;

  internal event NextMidLevelStepStartedEventHandler NextMidLevelStep;

  public TxInterferenceVolume_MayProceedCalculation Callback
  {
    set => this.m_mayProceedCallback = value;
  }

  public CApAIVCLogMessageEventHandler LogMessage
  {
    set => this.m_logMessage = value;
  }

  public TxObjectList InterferenceVolumes => this.m_interferenceVolumes;

  public TxObjectList RedundantSweptVolumes => this.m_redundantSVs;

  public CApAIVCInterferenceVolumesCreator()
  {
    this.m_ivCreator = (CApIVInterferenceVolumeCreator) null;
    // ISSUE: method pointer
    this.m_mayProceedCallback = new TxInterferenceVolume_MayProceedCalculation((object) this, __methodptr(MayProceed));
    this.m_shouldStop = false;
    this.m_interferenceVolumes = new TxObjectList();
    this.m_redundantSVs = this.m_volumesToClear = new TxObjectList();
    this.m_collidedSVs = new List<KeyValuePair<TxSweptVolume, TxSweptVolume>>();
    this.m_activePairs = new TxObjectList();
    this.DeactivateAndStoreAllActiveCollisionPairs();
    this.m_collisionPair = TxApplication.ActiveDocument.CollisionRoot.CreateCollisionPair(new TxCollisionPairCreationData("Interference Volume"));
    this.m_collisionPair.Active = true;
    this.m_queryParams = new TxCollisionQueryParams();
    this.m_queryParams.Mode = (TxCollisionQueryParams.TxCollisionQueryMode) 0;
    this.m_queryParams.UseNearMiss = false;
  }

  public void SweptVolumeCollisionDetection(Dictionary<ITxRobot, TxObjectList> sweptVolumes)
  {
    this.AreSVsOfTheSameRobot(sweptVolumes);
    int nVolumes = this.NumCollisionSets(sweptVolumes);
    this.m_sweptVolumes = this.SweptVolumeList(sweptVolumes);
    this.m_redundantSVs = new TxObjectList(this.m_sweptVolumes);
    HashSet<ITxRobot> itxRobotSet = new HashSet<ITxRobot>();
    Dictionary<ITxRobot, TxObjectList>.KeyCollection.Enumerator enumerator1 = sweptVolumes.Keys.GetEnumerator();
    while (enumerator1.MoveNext() && !this.m_shouldStop)
    {
      ITxRobot current1 = enumerator1.Current;
      Dictionary<ITxRobot, TxObjectList>.KeyCollection.Enumerator enumerator2 = sweptVolumes.Keys.GetEnumerator();
label_11:
      while (enumerator2.MoveNext() && !this.m_shouldStop)
      {
        ITxRobot current2 = enumerator2.Current;
        if (current1 != current2 && !itxRobotSet.Contains(current2))
        {
          TxObjectList sweptVolume1 = sweptVolumes[current1];
          TxObjectList sweptVolume2 = sweptVolumes[current2];
          int index1 = 0;
          while (true)
          {
            if (index1 < ((Collection<ITxObject>) sweptVolume1).Count && !this.m_shouldStop)
            {
              TxSweptVolume key = ((Collection<ITxObject>) sweptVolume1)[index1] as TxSweptVolume;
              key.Display();
              TxObjectList txObjectList1 = new TxObjectList(1);
              ((Collection<ITxObject>) txObjectList1).Add((ITxObject) key);
              this.m_collisionPair.FirstList = txObjectList1;
              for (int index2 = 0; index2 < ((Collection<ITxObject>) sweptVolume2).Count && !this.m_shouldStop; ++index2)
              {
                TxSweptVolume txSweptVolume = ((Collection<ITxObject>) sweptVolume2)[index2] as TxSweptVolume;
                txSweptVolume.Display();
                TxObjectList txObjectList2 = new TxObjectList(1);
                ((Collection<ITxObject>) txObjectList2).Add((ITxObject) txSweptVolume);
                this.m_collisionPair.SecondList = txObjectList2;
                this.FireMidLevelProgress(nVolumes);
                if (!this.m_shouldStop && this.DoesCollisionOccur())
                {
                  this.m_collidedSVs.Add(new KeyValuePair<TxSweptVolume, TxSweptVolume>(key, txSweptVolume));
                  ((Collection<ITxObject>) this.m_redundantSVs).Remove((ITxObject) key);
                  ((Collection<ITxObject>) this.m_redundantSVs).Remove((ITxObject) txSweptVolume);
                }
                txSweptVolume.Blank();
              }
              key.Blank();
              ++index1;
            }
            else
              goto label_11;
          }
        }
      }
      itxRobotSet.Add(current1);
    }
    this.finiCollisionDetection();
  }

  public void InterferenceVolumeCreation()
  {
    this.InitSweptVolumesToClear();
    int count = this.m_collidedSVs.Count;
    for (int index = 0; index < this.m_collidedSVs.Count && !this.m_shouldStop; ++index)
    {
      KeyValuePair<TxSweptVolume, TxSweptVolume> collidedSv = this.m_collidedSVs[index];
      this.FireMidLevelProgress(count);
      TxSweptVolume key = collidedSv.Key;
      TxSweptVolume secondSV = collidedSv.Value;
      if (TxSweptVolume.op_Inequality(key, (ITxObject) null) && TxSweptVolume.op_Inequality(secondSV, (ITxObject) null) && !this.m_shouldStop)
      {
        this.CreateSingleInterferenceVolume(key, secondSV);
        TxInterferenceVolume interferenceVolume = this.GetExistingInterferenceVolume(key, secondSV);
        if (TxInterferenceVolume.op_Inequality(interferenceVolume, (ITxObject) null))
        {
          interferenceVolume.Blank();
          ((Collection<ITxObject>) this.m_interferenceVolumes).Add((ITxObject) interferenceVolume);
          this.FireCreationSuccessLogMessage();
        }
      }
    }
    this.ClearRemainingSweptVolumeCollisionData();
    if (count != 0)
      return;
    this.FireNoVolumesLogMessage();
  }

  public void AbortCreation()
  {
    this.m_shouldStop = true;
    if (this.m_ivCreator == null)
      return;
    this.m_ivCreator.AbortCreation();
    this.m_ivCreator = (CApIVInterferenceVolumeCreator) null;
  }

  private void AreSVsOfTheSameRobot(Dictionary<ITxRobot, TxObjectList> sweptVolumes)
  {
    if (sweptVolumes.Count != 1)
      return;
    this.FireAllSVsOfTheSameRobotLogMessage();
  }

  private void finiCollisionDetection()
  {
    this.DeleteCollisionPair();
    this.ActivateStoredCollisionPairs();
    if (this.m_shouldStop)
      return;
    this.FireCollisionDetectionLogMessage();
  }

  private void DeactivateAndStoreAllActiveCollisionPairs()
  {
    TxCollisionRoot collisionRoot = TxApplication.ActiveDocument.CollisionRoot;
    ((Collection<ITxObject>) this.m_activePairs).Clear();
    foreach (TxCollisionPair pair in (Collection<ITxObject>) collisionRoot.PairList)
    {
      if (TxCollisionPair.op_Inequality(pair, (ITxObject) null) && pair.Active)
      {
        ((Collection<ITxObject>) this.m_activePairs).Add((ITxObject) pair);
        pair.Active = false;
      }
    }
  }

  private void ActivateStoredCollisionPairs()
  {
    foreach (TxCollisionPair activePair in (Collection<ITxObject>) this.m_activePairs)
    {
      if (TxCollisionPair.op_Inequality(activePair, (ITxObject) null))
        activePair.Active = true;
    }
    ((Collection<ITxObject>) this.m_activePairs).Clear();
  }

  private void DeleteCollisionPair()
  {
    if (!TxCollisionPair.op_Inequality(this.m_collisionPair, (ITxObject) null))
      return;
    this.m_collisionPair.Delete();
    this.m_collisionPair = (TxCollisionPair) null;
  }

  private bool DoesCollisionOccur()
  {
    bool flag = false;
    if (TxApplication.ActiveDocument.CollisionRoot.GetCollidingObjects(this.m_queryParams).States.Count > 0)
      flag = true;
    return flag;
  }

  private int NumCollisionSets(Dictionary<ITxRobot, TxObjectList> sweptVolumes)
  {
    int num = 0;
    foreach (ITxRobot key1 in sweptVolumes.Keys)
    {
      foreach (ITxRobot key2 in sweptVolumes.Keys)
      {
        if (key1 != key2)
        {
          int count1 = ((Collection<ITxObject>) sweptVolumes[key1]).Count;
          int count2 = ((Collection<ITxObject>) sweptVolumes[key2]).Count;
          num += count1 * count2;
        }
      }
    }
    return num / 2;
  }

  private TxObjectList SweptVolumeList(Dictionary<ITxRobot, TxObjectList> sweptVolumes)
  {
    TxObjectList txObjectList1 = new TxObjectList();
    foreach (TxObjectList txObjectList2 in sweptVolumes.Values)
      ((TxObjectList<ITxObject>) txObjectList1).AddRange((TxObjectList<ITxObject>) txObjectList2);
    return txObjectList1;
  }

  private void CreateSingleInterferenceVolume(TxSweptVolume firstSV, TxSweptVolume secondSV)
  {
    this.ClearSweptVolumeCollisionData(firstSV);
    this.m_ivData = new CApAIVCInterferenceVolumeDataProvider(firstSV, secondSV);
    CUiIVNotificationFeedbackEventHandler feedbackEventHandler = new CUiIVNotificationFeedbackEventHandler(this.NotificationFeedback);
    this.m_ivCreator = new CApIVInterferenceVolumeCreator((IUiIVInterferenceVolumeDataProvider) this.m_ivData);
    this.m_ivCreator.NotificationFeedback = feedbackEventHandler;
    this.m_ivCreator.CallBack = this.m_mayProceedCallback;
    this.m_ivCreator.Create();
    firstSV.Blank();
    secondSV.Blank();
  }

  private TxInterferenceVolume GetExistingInterferenceVolume(
    TxSweptVolume firstSV,
    TxSweptVolume secondSV)
  {
    TxObjectList sweptVolumes = new TxObjectList();
    ((Collection<ITxObject>) sweptVolumes).Add((ITxObject) firstSV);
    ((Collection<ITxObject>) sweptVolumes).Add((ITxObject) secondSV);
    return CApIVUtilities.GetExistingInterferenceVolume(sweptVolumes);
  }

  private void InitSweptVolumesToClear()
  {
    this.m_volumesToClear = new TxObjectList(this.m_sweptVolumes);
    if (this.m_collidedSVs.Count > 0)
      this.m_currentVolumeToClear = this.m_collidedSVs[0].Key;
    foreach (TxSweptVolume redundantSv in (Collection<ITxObject>) this.m_redundantSVs)
    {
      TxCollisionRootEx.CollisionClearVolume((ITxObject) redundantSv);
      ((Collection<ITxObject>) this.m_volumesToClear).Remove((ITxObject) redundantSv);
    }
  }

  private void ClearSweptVolumeCollisionData(TxSweptVolume currentSV)
  {
    if (!TxSweptVolume.op_Inequality(currentSV, (ITxObject) this.m_currentVolumeToClear))
      return;
    TxCollisionRootEx.CollisionClearVolume((ITxObject) this.m_currentVolumeToClear);
    ((Collection<ITxObject>) this.m_volumesToClear).Remove((ITxObject) this.m_currentVolumeToClear);
    this.m_currentVolumeToClear = currentSV;
  }

  private void ClearRemainingSweptVolumeCollisionData()
  {
    foreach (ITxObject itxObject in (Collection<ITxObject>) this.m_volumesToClear)
      TxCollisionRootEx.CollisionClearVolume(itxObject);
  }

  private void FireMidLevelProgress(int nVolumes)
  {
    if (this.NextMidLevelStep == null)
      return;
    this.NextMidLevelStep((object) this, new NextMidLevelStepStartedEventArgs(nVolumes));
  }

  private bool MayProceed(int progress) => true;

  private void NotificationFeedback(object sender, CUiIVNotificationFeedbackEventArgs args)
  {
    switch (args.Notification.Code)
    {
      case eUiIVNotificationCode.CAN_CREATE_WARNING_BLANKED_SWEPT_VOLUMES:
        args.FeedbackResult = CUiIVNotificationFeedbackEventArgs.eFeedbackResult.Yes;
        break;
      case eUiIVNotificationCode.CREATE_ERR_INTERFERENCE_VOLUME_CREATE_FAIL:
      case eUiIVNotificationCode.CREATE_ERR_INTERFERENCE_VOLUME_CALCULATE_FAIL:
        this.FireCreationErrorLogMessage();
        break;
    }
  }

  private void FireLogMessage(CApAIVCLogMessage message)
  {
    if (this.m_logMessage == null || message == null)
      return;
    this.m_logMessage((object) this, new CApAIVCLogMessageEventArgs(message));
  }

  private void FireCreationErrorLogMessage()
  {
    this.FireLogMessage(new CApAIVCLogMessage(eApAIVCLogCode.INTERFERENCE_VOLUME_CREATION_FAILED, this.m_ivData.IVData_Name));
  }

  private void FireCreationSuccessLogMessage()
  {
    this.FireLogMessage(new CApAIVCLogMessage(eApAIVCLogCode.INTERFERENCE_VOLUME_CREATION_SUCCEEDED, this.m_ivData.IVData_Name));
  }

  private void FireCollisionDetectionLogMessage()
  {
    this.FireLogMessage(new CApAIVCLogMessage(eApAIVCLogCode.SWEPT_VOLUME_COLLISION, this.m_collidedSVs.Count));
  }

  private void FireNoVolumesLogMessage()
  {
    this.FireLogMessage(new CApAIVCLogMessage(eApAIVCLogCode.INTERFERENCE_VOLUME_NO_VOLUMES));
  }

  private void FireAllSVsOfTheSameRobotLogMessage()
  {
    this.FireLogMessage(new CApAIVCLogMessage(eApAIVCLogCode.SWEPT_VOLUME_SAME_ROBOT));
  }
}
